{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note** : The examples presented below are the copy of the ones presented on https://github.com/bbecquet/Leaflet.PolylineOffset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Basic Demo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- The dashed line is the \"model\", with no offset applied. \n",
    "- The Red line is with a -5px offset,\n",
    "- The Green line is with a 10px offset.\n",
    "The three are distinct Polyline objects but uses the same coordinate array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><span style=\"color:#565656\">Make this Notebook Trusted to load map: File -> Trust Notebook</span><iframe src=\"about:blank\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" data-html=PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS42LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS42LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUubWluLmNzcyIvPgogICAgCiAgICAgICAgICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsCiAgICAgICAgICAgICAgICBpbml0aWFsLXNjYWxlPTEuMCwgbWF4aW11bS1zY2FsZT0xLjAsIHVzZXItc2NhbGFibGU9bm8iIC8+CiAgICAgICAgICAgIDxzdHlsZT4KICAgICAgICAgICAgICAgICNtYXBfMjk2YjFjZmNkMDBkNDVhNWFjNWM1MGNiMWUwMjE3OGYgewogICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgICAgICB3aWR0aDogMTAwLjAlOwogICAgICAgICAgICAgICAgICAgIGhlaWdodDogMTAwLjAlOwogICAgICAgICAgICAgICAgICAgIGxlZnQ6IDAuMCU7CiAgICAgICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldC1wb2x5bGluZW9mZnNldEAxLjEuMS9sZWFmbGV0LnBvbHlsaW5lb2Zmc2V0Lm1pbi5qcyI+PC9zY3JpcHQ+CjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfMjk2YjFjZmNkMDBkNDVhNWFjNWM1MGNiMWUwMjE3OGYiID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzI5NmIxY2ZjZDAwZDQ1YTVhYzVjNTBjYjFlMDIxNzhmID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzI5NmIxY2ZjZDAwZDQ1YTVhYzVjNTBjYjFlMDIxNzhmIiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFs1OC4wLCAtMTEuMF0sCiAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICAgICAgICAgICAgICB6b29tOiA0LAogICAgICAgICAgICAgICAgICAgIHpvb21Db250cm9sOiB0cnVlLAogICAgICAgICAgICAgICAgICAgIHByZWZlckNhbnZhczogZmFsc2UsCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICk7CgogICAgICAgICAgICAKCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfM2Y0NWMwNzdiNzVjNDc2Y2E2OGJiZDQ3NmMwYjM3MzIgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICJodHRwczovL2NhcnRvZGItYmFzZW1hcHMte3N9Lmdsb2JhbC5zc2wuZmFzdGx5Lm5ldC9saWdodF9hbGwve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiXHUwMDI2Y29weTsgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSBjb250cmlidXRvcnMgXHUwMDI2Y29weTsgXHUwMDNjYSBocmVmPVwiaHR0cDovL2NhcnRvZGIuY29tL2F0dHJpYnV0aW9uc1wiXHUwMDNlQ2FydG9EQlx1MDAzYy9hXHUwMDNlLCBDYXJ0b0RCIFx1MDAzY2EgaHJlZiA9XCJodHRwOi8vY2FydG9kYi5jb20vYXR0cmlidXRpb25zXCJcdTAwM2VhdHRyaWJ1dGlvbnNcdTAwM2MvYVx1MDAzZSIsICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwgIm1heE5hdGl2ZVpvb20iOiAxOCwgIm1heFpvb20iOiAxOCwgIm1pblpvb20iOiAwLCAibm9XcmFwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInN1YmRvbWFpbnMiOiAiYWJjIiwgInRtcyI6IGZhbHNlfQogICAgICAgICAgICApLmFkZFRvKG1hcF8yOTZiMWNmY2QwMGQ0NWE1YWM1YzUwY2IxZTAyMTc4Zik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfMjlkNWYzYzAyODg3NDU3ZGIyYTBjZTZmN2ViMjNhMDMgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s1OC40NDc3MywgLTI4LjY1MjM0XSwgWzUzLjAsIC0yMy4zMzQ5Nl0sIFs1My4wLCAtMTQuMzI2MTddLCBbNTguMTcwNywgLTEwLjM3MTA5XSwgWzU5LjAsIC0xMy4wXSwgWzU3LjAsIC0xNS4wXSwgWzU3LjAsIC0xOC4wXSwgWzYwLjAsIC0xOC4wXSwgWzYzLjAsIC01LjBdLCBbNTkuMCwgLTcuMF0sIFs1OC4wLCAtMy4wXSwgWzU2LjAsIC0zLjBdLCBbNjAuMCwgLTQuMF1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogImJsYWNrIiwgImRhc2hBcnJheSI6ICI1LDEwIiwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogImJsYWNrIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMCwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDJ9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzI5NmIxY2ZjZDAwZDQ1YTVhYzVjNTBjYjFlMDIxNzhmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF85Zjk1MTM5MGZiNGQ0NWFlOGFjNDcxMjI0NmY1ZWI0MSA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzU4LjQ0NzczLCAtMjguNjUyMzRdLCBbNTMuMCwgLTIzLjMzNDk2XSwgWzUzLjAsIC0xNC4zMjYxN10sIFs1OC4xNzA3LCAtMTAuMzcxMDldLCBbNTkuMCwgLTEzLjBdLCBbNTcuMCwgLTE1LjBdLCBbNTcuMCwgLTE4LjBdLCBbNjAuMCwgLTE4LjBdLCBbNjMuMCwgLTUuMF0sIFs1OS4wLCAtNy4wXSwgWzU4LjAsIC0zLjBdLCBbNTYuMCwgLTMuMF0sIFs2MC4wLCAtNC4wXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2YwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2YwMCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IC01LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogM30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfMjk2YjFjZmNkMDBkNDVhNWFjNWM1MGNiMWUwMjE3OGYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0X2Q3YmMzZDM1ZjdiMDRjMWE4MDQ2MTA5ZDFlMGI4ZmNkID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNTguNDQ3NzMsIC0yOC42NTIzNF0sIFs1My4wLCAtMjMuMzM0OTZdLCBbNTMuMCwgLTE0LjMyNjE3XSwgWzU4LjE3MDcsIC0xMC4zNzEwOV0sIFs1OS4wLCAtMTMuMF0sIFs1Ny4wLCAtMTUuMF0sIFs1Ny4wLCAtMTguMF0sIFs2MC4wLCAtMTguMF0sIFs2My4wLCAtNS4wXSwgWzU5LjAsIC03LjBdLCBbNTguMCwgLTMuMF0sIFs1Ni4wLCAtMy4wXSwgWzYwLjAsIC00LjBdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDgwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDgwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMTAsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8yOTZiMWNmY2QwMGQ0NWE1YWM1YzUwY2IxZTAyMTc4Zik7CiAgICAgICAgCjwvc2NyaXB0Pg== onload=\"this.contentDocument.open();this.contentDocument.write(atob(this.getAttribute('data-html')));this.contentDocument.close();\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x7f593c37d730>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import folium\n",
    "from folium import plugins\n",
    "\n",
    "\n",
    "m = folium.Map(location=[58.0, -11.0], zoom_start=4, tiles=\"cartodbpositron\")\n",
    "\n",
    "coords = [\n",
    "    [58.44773, -28.65234],\n",
    "    [53, -23.33496],\n",
    "    [53, -14.32617],\n",
    "    [58.1707, -10.37109],\n",
    "    [59, -13],\n",
    "    [57, -15],\n",
    "    [57, -18],\n",
    "    [60, -18],\n",
    "    [63, -5],\n",
    "    [59, -7],\n",
    "    [58, -3],\n",
    "    [56, -3],\n",
    "    [60, -4],\n",
    "]\n",
    "\n",
    "plugins.PolyLineOffset(\n",
    "    coords, weight=2, dash_array=\"5,10\", color=\"black\", opacity=1\n",
    ").add_to(m)\n",
    "\n",
    "plugins.PolyLineOffset(coords, color=\"#f00\", opacity=1, offset=-5).add_to(m)\n",
    "\n",
    "plugins.PolyLineOffset(coords, color=\"#080\", opacity=1, offset=10).add_to(m)\n",
    "\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bus Lines"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A more complex demo. \n",
    "Offsets are computed automatically depending on the number of bus lines using the same segment.\n",
    "Other non-offset polylines are used to achieve the white and black outline effect."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><span style=\"color:#565656\">Make this Notebook Trusted to load map: File -> Trust Notebook</span><iframe src=\"about:blank\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" data-html=PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHN0eWxlPmh0bWwsIGJvZHkge3dpZHRoOiAxMDAlO2hlaWdodDogMTAwJTttYXJnaW46IDA7cGFkZGluZzogMDt9PC9zdHlsZT4KICAgIDxzdHlsZT4jbWFwIHtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6MDtib3R0b206MDtyaWdodDowO2xlZnQ6MDt9PC9zdHlsZT4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS42LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS42LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L2doL3B5dGhvbi12aXN1YWxpemF0aW9uL2ZvbGl1bS9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUubWluLmNzcyIvPgogICAgCiAgICAgICAgICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsCiAgICAgICAgICAgICAgICBpbml0aWFsLXNjYWxlPTEuMCwgbWF4aW11bS1zY2FsZT0xLjAsIHVzZXItc2NhbGFibGU9bm8iIC8+CiAgICAgICAgICAgIDxzdHlsZT4KICAgICAgICAgICAgICAgICNtYXBfMDViZjQ4M2I3YjU2NDRlYmE2ZmQwNTgxOTQ3YTMwZjcgewogICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTsKICAgICAgICAgICAgICAgICAgICB3aWR0aDogMTAwLjAlOwogICAgICAgICAgICAgICAgICAgIGhlaWdodDogMTAwLjAlOwogICAgICAgICAgICAgICAgICAgIGxlZnQ6IDAuMCU7CiAgICAgICAgICAgICAgICAgICAgdG9wOiAwLjAlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldC1wb2x5bGluZW9mZnNldEAxLjEuMS9sZWFmbGV0LnBvbHlsaW5lb2Zmc2V0Lm1pbi5qcyI+PC9zY3JpcHQ+CjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfMDViZjQ4M2I3YjU2NDRlYmE2ZmQwNTgxOTQ3YTMwZjciID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzA1YmY0ODNiN2I1NjQ0ZWJhNmZkMDU4MTk0N2EzMGY3ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzA1YmY0ODNiN2I1NjQ0ZWJhNmZkMDU4MTk0N2EzMGY3IiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFs0OC44NjgsIDIuMzY1XSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDE1LAogICAgICAgICAgICAgICAgICAgIHpvb21Db250cm9sOiB0cnVlLAogICAgICAgICAgICAgICAgICAgIHByZWZlckNhbnZhczogZmFsc2UsCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICk7CgogICAgICAgICAgICAKCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfNzM1NzcyOTBkYjljNDY4ZWI0ZGE5YmUxNDQ2MjkzYTMgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICJodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZyIsCiAgICAgICAgICAgICAgICB7ImF0dHJpYnV0aW9uIjogIkRhdGEgYnkgXHUwMDI2Y29weTsgXHUwMDNjYSBocmVmPVwiaHR0cDovL29wZW5zdHJlZXRtYXAub3JnXCJcdTAwM2VPcGVuU3RyZWV0TWFwXHUwMDNjL2FcdTAwM2UsIHVuZGVyIFx1MDAzY2EgaHJlZj1cImh0dHA6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvY29weXJpZ2h0XCJcdTAwM2VPRGJMXHUwMDNjL2FcdTAwM2UuIiwgImRldGVjdFJldGluYSI6IGZhbHNlLCAibWF4TmF0aXZlWm9vbSI6IDE4LCAibWF4Wm9vbSI6IDE4LCAibWluWm9vbSI6IDAsICJub1dyYXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic3ViZG9tYWlucyI6ICJhYmMiLCAidG1zIjogZmFsc2V9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzA1YmY0ODNiN2I1NjQ0ZWJhNmZkMDU4MTk0N2EzMGY3KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgZmVhdHVyZV9ncm91cF8xYmY1ZWY5MzJlYmU0MTg2YTA3OWQyOGQ5M2U5ZTAxMSA9IEwuZmVhdHVyZUdyb3VwKAogICAgICAgICAgICAgICAge30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfMDViZjQ4M2I3YjU2NDRlYmE2ZmQwNTgxOTQ3YTMwZjcpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfOTNkZTczMjZlYjJhNDIxZTk4ZTYyNjk5MTY5OTQwNTkgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NzYyMTc3MzMyNDE1MywgMi4zNTc5MTkyMTYxNTYwMDZdLCBbNDguODc0ODM0NjkzNzMxNjY0LCAyLjM1NzMzOTg1OTAwODc4OV0sIFs0OC44Njg1NTQwODQzMjc0OSwgMi4zNjI5ODMyMjY3NzYxMjNdLCBbNDguODY3OTYxMjY2OTkxNjgsIDIuMzYyMzgyNDExOTU2Nzg3XSwgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDAwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMTl9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8xYmY1ZWY5MzJlYmU0MTg2YTA3OWQyOGQ5M2U5ZTAxMSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9lZjJmZDFhZDVjNTE0OTE0OGM0NDNjMDVmODZhNTg0ZiA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NDQzOTUwNDkzODIzLCAyLjM1MTUwMzM3MjE5MjM4M10sIFs0OC44NjY3NzU2MTEyNTAyMDUsIDIuMzYxNjA5OTM1NzYwNDk4XSwgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDAwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMTl9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8xYmY1ZWY5MzJlYmU0MTg2YTA3OWQyOGQ5M2U5ZTAxMSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9hZGFiZTYzYTQzZmU0MTRmODA3Njc0YmM4ZjllMmZiZiA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sIFs0OC44NjI2Mzk3MTEyMDQyLCAyLjM3MjQwMzE0NDgzNjQyNTNdLCBbNDguODYxNjIzMzI4NTAwMSwgMi4zNzI4MzIyOTgyNzg4MDg2XSwgWzQ4Ljg2MDgwNDU2MDc1NTY3LCAyLjM3Mjc2NzkyNTI2MjQ1MV1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAxOX0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzFiZjVlZjkzMmViZTQxODZhMDc5ZDI4ZDkzZTllMDExKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzk4NThmMmU1ZGM1ZTRmZmRhYTIyZGIzMGM3ZjI3ZTcxID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl0sIFs0OC44NjYzMDk4MTAyMzY5NCwgMi4zNjQ3NjQyMTM1NjIwMTE3XSwgWzQ4Ljg2MzE0Nzg5NDgxNjEyLCAyLjM2NjY3Mzk0NjM4MDYxNTJdLCBbNDguODYwNjYzMzkyNTQ5NDQsIDIuMzY3MzE3Njc2NTQ0MTg5NV1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAxMn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzFiZjVlZjkzMmViZTQxODZhMDc5ZDI4ZDkzZTllMDExKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX2RkNDY2ZjJlYzM2NDRhZDA5MzA2MzQwOWVmYTY0ZDk5ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M10sIFs0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzAwMCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDMzfQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMWJmNWVmOTMyZWJlNDE4NmEwNzlkMjhkOTNlOWUwMTEpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfNDJkYWU3ZTFmM2FjNDM2MmEyMWJjODkyNTJiMzkzZTkgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwgWzQ4Ljg2NjYwNjIyOTU2NTI0LCAyLjM2NTAwMDI0Nzk1NTMyMjNdLCBbNDguODY2OTg3MzM3NTUwMTY0LCAyLjM2NTUwOTg2NzY2ODE1Ml0sIFs0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDAwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMjZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8xYmY1ZWY5MzJlYmU0MTg2YTA3OWQyOGQ5M2U5ZTAxMSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV8wNWM3MTAyYWNkZTY0MzE4ODIyMWI2NGRkY2I1MjUyNyA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sIFs0OC44NjU3MDI4NTA4OTU3NDQsIDIuMzcyMzQ5NTAwNjU2MTI4XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzAwMCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDEyfQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMWJmNWVmOTMyZWJlNDE4NmEwNzlkMjhkOTNlOWUwMTEpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBmZWF0dXJlX2dyb3VwXzY0YTA2YzE1MjUyOTRkNWQ5ODI2MzQ1OWJmOTk4ZWU4ID0gTC5mZWF0dXJlR3JvdXAoCiAgICAgICAgICAgICAgICB7fQogICAgICAgICAgICApLmFkZFRvKG1hcF8wNWJmNDgzYjdiNTY0NGViYTZmZDA1ODE5NDdhMzBmNyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV81MTAyOGI1NTE2ZDc0NzRmOGE5ZmFiM2Q2YjU0OWRmMSA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg3NjIxNzczMzI0MTUzLCAyLjM1NzkxOTIxNjE1NjAwNl0sIFs0OC44NzQ4MzQ2OTM3MzE2NjQsIDIuMzU3MzM5ODU5MDA4Nzg5XSwgWzQ4Ljg2ODU1NDA4NDMyNzQ5LCAyLjM2Mjk4MzIyNjc3NjEyM10sIFs0OC44Njc5NjEyNjY5OTE2OCwgMi4zNjIzODI0MTE5NTY3ODddLCBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M11dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiNmZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAxN30KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY0YTA2YzE1MjUyOTRkNWQ5ODI2MzQ1OWJmOTk4ZWU4KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzRjODBkZmM3NjYwMzRkZDJiNjI0ZDdhZjk2ZWY4Y2U5ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY0NDM5NTA0OTM4MjMsIDIuMzUxNTAzMzcyMTkyMzgzXSwgWzQ4Ljg2Njc3NTYxMTI1MDIwNSwgMi4zNjE2MDk5MzU3NjA0OThdLCBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M11dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiNmZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAxN30KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY0YTA2YzE1MjUyOTRkNWQ5ODI2MzQ1OWJmOTk4ZWU4KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX2E2ODdiMWNiNGE4NjQ3ZTk4MWZkNjZkNDRiNDJjYThlID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXSwgWzQ4Ljg2MjYzOTcxMTIwNDIsIDIuMzcyNDAzMTQ0ODM2NDI1M10sIFs0OC44NjE2MjMzMjg1MDAxLCAyLjM3MjgzMjI5ODI3ODgwODZdLCBbNDguODYwODA0NTYwNzU1NjcsIDIuMzcyNzY3OTI1MjYyNDUxXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2ZmZiIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDE3fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNjRhMDZjMTUyNTI5NGQ1ZDk4MjYzNDU5YmY5OThlZTgpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfNGU5ODZkNDMyOTc4NDk0NWIwZDEwYTcwZTNjMmMzOTQgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwgWzQ4Ljg2NjMwOTgxMDIzNjk0LCAyLjM2NDc2NDIxMzU2MjAxMTddLCBbNDguODYzMTQ3ODk0ODE2MTIsIDIuMzY2NjczOTQ2MzgwNjE1Ml0sIFs0OC44NjA2NjMzOTI1NDk0NCwgMi4zNjczMTc2NzY1NDQxODk1XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2ZmZiIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDEwfQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNjRhMDZjMTUyNTI5NGQ1ZDk4MjYzNDU5YmY5OThlZTgpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfOWI5YjQ1ZWZkOTQ0NDkzZWIyMjM3MzVlYzQ5YzNmNzUgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXSwgWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZmZmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMzF9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF82NGEwNmMxNTI1Mjk0ZDVkOTgyNjM0NTliZjk5OGVlOCk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9jZmY2ODJjN2Q5NDM0MDRkOTRiNDc0YzIyNDQwNzBhMCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdLCBbNDguODY2NjA2MjI5NTY1MjQsIDIuMzY1MDAwMjQ3OTU1MzIyM10sIFs0OC44NjY5ODczMzc1NTAxNjQsIDIuMzY1NTA5ODY3NjY4MTUyXSwgWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiNmZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAyNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY0YTA2YzE1MjUyOTRkNWQ5ODI2MzQ1OWJmOTk4ZWU4KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzgwNzI5NGRjNTFkMjRiYjE5NDM5NWZkMzY5YTQxOTllID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXSwgWzQ4Ljg2NTcwMjg1MDg5NTc0NCwgMi4zNzIzNDk1MDA2NTYxMjhdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZmZmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMTB9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF82NGEwNmMxNTI1Mjk0ZDVkOTgyNjM0NTliZjk5OGVlOCk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGZlYXR1cmVfZ3JvdXBfMDAwYWRjZmFjNzNmNGYxYWJmYzJlYzM5MzhhMzQzM2IgPSBMLmZlYXR1cmVHcm91cCgKICAgICAgICAgICAgICAgIHt9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzA1YmY0ODNiN2I1NjQ0ZWJhNmZkMDU4MTk0N2EzMGY3KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF8yMGYyZGFhNWMzMWE0YjVmOTZhYWQzNTdiYzVmYTc2MCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg3NjIxNzczMzI0MTUzLCAyLjM1NzkxOTIxNjE1NjAwNl0sIFs0OC44NzQ4MzQ2OTM3MzE2NjQsIDIuMzU3MzM5ODU5MDA4Nzg5XSwgWzQ4Ljg2ODU1NDA4NDMyNzQ5LCAyLjM2Mjk4MzIyNjc3NjEyM10sIFs0OC44Njc5NjEyNjY5OTE2OCwgMi4zNjIzODI0MTE5NTY3ODddLCBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M11dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogInJlZCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAicmVkIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogLTMuNSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDBhZGNmYWM3M2Y0ZjFhYmZjMmVjMzkzOGEzNDMzYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfMjIyMGRjNGMyZGM4NGNkN2EyNjYwMzZhNWQzMGIyY2YgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NzYyMTc3MzMyNDE1MywgMi4zNTc5MTkyMTYxNTYwMDZdLCBbNDguODc0ODM0NjkzNzMxNjY0LCAyLjM1NzMzOTg1OTAwODc4OV0sIFs0OC44Njg1NTQwODQzMjc0OSwgMi4zNjI5ODMyMjY3NzYxMjNdLCBbNDguODY3OTYxMjY2OTkxNjgsIDIuMzYyMzgyNDExOTU2Nzg3XSwgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDhmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDhmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMy41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwMGFkY2ZhYzczZjRmMWFiZmMyZWMzOTM4YTM0MzNiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF9jZjk4Y2RiNTczZWY0NjczOWNkZTdkOTE4NDhiZDA5ZiA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NDQzOTUwNDkzODIzLCAyLjM1MTUwMzM3MjE5MjM4M10sIFs0OC44NjY3NzU2MTEyNTAyMDUsIDIuMzYxNjA5OTM1NzYwNDk4XSwgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMGMwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMGMwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogLTMuNSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDBhZGNmYWM3M2Y0ZjFhYmZjMmVjMzkzOGEzNDMzYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfOWMwMGZiOGYyZDRlNDIwYjkwNmVlMmZjMTFiYmMxMDAgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjQ0Mzk1MDQ5MzgyMywgMi4zNTE1MDMzNzIxOTIzODNdLCBbNDguODY2Nzc1NjExMjUwMjA1LCAyLjM2MTYwOTkzNTc2MDQ5OF0sIFs0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2Y4MCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2Y4MCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IDMuNSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDBhZGNmYWM3M2Y0ZjFhYmZjMmVjMzkzOGEzNDMzYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfZGIyOTI0NGQ3NDM2NGM3ODhmYjZkMWY1M2NmYjViMDEgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdLCBbNDguODYyNjM5NzExMjA0MiwgMi4zNzI0MDMxNDQ4MzY0MjUzXSwgWzQ4Ljg2MTYyMzMyODUwMDEsIDIuMzcyODMyMjk4Mjc4ODA4Nl0sIFs0OC44NjA4MDQ1NjA3NTU2NywgMi4zNzI3Njc5MjUyNjI0NTFdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDhmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDhmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogLTMuNSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDBhZGNmYWM3M2Y0ZjFhYmZjMmVjMzkzOGEzNDMzYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfZWZkNmQyOGI5Y2ZjNGJjMDkzYWNjZGYwN2E0MmNlNjMgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdLCBbNDguODYyNjM5NzExMjA0MiwgMi4zNzI0MDMxNDQ4MzY0MjUzXSwgWzQ4Ljg2MTYyMzMyODUwMDEsIDIuMzcyODMyMjk4Mjc4ODA4Nl0sIFs0OC44NjA4MDQ1NjA3NTU2NywgMi4zNzI3Njc5MjUyNjI0NTFdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMGMwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMGMwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMy41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwMGFkY2ZhYzczZjRmMWFiZmMyZWMzOTM4YTM0MzNiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF9lYWVhY2VjY2U0ZmU0NGI4YmJkNjViNTE0NWQwY2M3YSA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdLCBbNDguODY2MzA5ODEwMjM2OTQsIDIuMzY0NzY0MjEzNTYyMDExN10sIFs0OC44NjMxNDc4OTQ4MTYxMiwgMi4zNjY2NzM5NDYzODA2MTUyXSwgWzQ4Ljg2MDY2MzM5MjU0OTQ0LCAyLjM2NzMxNzY3NjU0NDE4OTVdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICJyZWQiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogInJlZCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IDAuMCwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDBhZGNmYWM3M2Y0ZjFhYmZjMmVjMzkzOGEzNDMzYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfZWQxOWNjOTYxMmVkNGY3NmI3MDYwZGRmZGVmMjUxMjcgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXSwgWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICJyZWQiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogInJlZCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IC0xMC41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwMGFkY2ZhYzczZjRmMWFiZmMyZWMzOTM4YTM0MzNiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF80ZjY0NGU0ZWY5ZjE0MDU1YWYxZDhiOTA5Y2ZkMTU0OCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdLCBbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwOGYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwOGYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAtMy41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwMGFkY2ZhYzczZjRmMWFiZmMyZWMzOTM4YTM0MzNiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF83ZTg5MjdhMTE4ZjM0OWZlYTY5OGVhMzc0OTA5Yzg0ZiA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdLCBbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwYzAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwYzAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAzLjUsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMDAwYWRjZmFjNzNmNGYxYWJmYzJlYzM5MzhhMzQzM2IpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0XzQxMTE2MWRhNmQ5MTQ1M2NiMjAyYTM1OTQ5NWVjN2RmID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M10sIFs0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2Y4MCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2Y4MCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IDEwLjUsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMDAwYWRjZmFjNzNmNGYxYWJmYzJlYzM5MzhhMzQzM2IpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0XzNmOWE2NmZmNWZkZjQ2MjM5NzViNDNiMjNiMjM2NGE0ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl0sIFs0OC44NjY2MDYyMjk1NjUyNCwgMi4zNjUwMDAyNDc5NTUzMjIzXSwgWzQ4Ljg2Njk4NzMzNzU1MDE2NCwgMi4zNjU1MDk4Njc2NjgxNTJdLCBbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzA4ZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzA4ZiIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IC03LjAsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMDAwYWRjZmFjNzNmNGYxYWJmYzJlYzM5MzhhMzQzM2IpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0XzUzNmE4OTAxY2U4ZDQ2ZWI4MGQ2NjU0MmZmM2I2N2IzID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl0sIFs0OC44NjY2MDYyMjk1NjUyNCwgMi4zNjUwMDAyNDc5NTUzMjIzXSwgWzQ4Ljg2Njk4NzMzNzU1MDE2NCwgMi4zNjU1MDk4Njc2NjgxNTJdLCBbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzBjMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzBjMCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IDAuMCwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDBhZGNmYWM3M2Y0ZjFhYmZjMmVjMzkzOGEzNDMzYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfM2MxN2MxOWQxNDEzNDM3ZWIwYzcwYmIyMGJlZDQ0NzcgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwgWzQ4Ljg2NjYwNjIyOTU2NTI0LCAyLjM2NTAwMDI0Nzk1NTMyMjNdLCBbNDguODY2OTg3MzM3NTUwMTY0LCAyLjM2NTUwOTg2NzY2ODE1Ml0sIFs0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZjgwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZjgwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogNy4wLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzAwMGFkY2ZhYzczZjRmMWFiZmMyZWMzOTM4YTM0MzNiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF9iYjhjYzliYjE1MDk0MjkwOWExMTg2Mzg0MGI4ZDFhZCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sIFs0OC44NjU3MDI4NTA4OTU3NDQsIDIuMzcyMzQ5NTAwNjU2MTI4XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2Y4MCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2Y4MCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IDAuMCwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wMDBhZGNmYWM3M2Y0ZjFhYmZjMmVjMzkzOGEzNDMzYik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGZlYXR1cmVfZ3JvdXBfMGU3OThhZWE1M2Y3NDUwZGJhZDY5YzhiNzQ1M2U1MDMgPSBMLmZlYXR1cmVHcm91cCgKICAgICAgICAgICAgICAgIHt9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzA1YmY0ODNiN2I1NjQ0ZWJhNmZkMDU4MTk0N2EzMGY3KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8xNDk2ZTM1NjJlMDQ0ZDJhOTA4OTJkNDhjZjU4NTAxNyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg3NjIxNzczMzI0MTUzLCAyLjM1NzkxOTIxNjE1NjAwNl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wZTc5OGFlYTUzZjc0NTBkYmFkNjljOGI3NDUzZTUwMyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfYjY5OWE0M2M2YjNmNDRkZGFkOTRiOTgzNmEyOWZmY2UgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzBlNzk4YWVhNTNmNzQ1MGRiYWQ2OWM4Yjc0NTNlNTAzKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9jMWNlOTM2MzNlNjg0MjFmOGNlOGIyNGM3ZmE2NDIyZiA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NDQzOTUwNDkzODIzLCAyLjM1MTUwMzM3MjE5MjM4M10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wZTc5OGFlYTUzZjc0NTBkYmFkNjljOGI3NDUzZTUwMyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNGEyZDA5YmRhZmMzNGI5OTg4NGExODE1MWIyNzAxNDIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzBlNzk4YWVhNTNmNzQ1MGRiYWQ2OWM4Yjc0NTNlNTAzKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84ZGY1OTg5MmQ4MzM0MGFiYmU5OTEwMTYyYWMwYjRlZSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wZTc5OGFlYTUzZjc0NTBkYmFkNjljOGI3NDUzZTUwMyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNjhiNDk1YzIxNTE0NGExNzk1NTgyZTk2ZTViYjJlZGYgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjA4MDQ1NjA3NTU2NywgMi4zNzI3Njc5MjUyNjI0NTFdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2NjYyIsICJmaWxsT3BhY2l0eSI6IDEsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEsICJyYWRpdXMiOiAxMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMGU3OThhZWE1M2Y3NDUwZGJhZDY5YzhiNzQ1M2U1MDMpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhiNGEwNjU3ZmViMDQ5YTVhNWI2YjE2OTk3MGJkYzQ3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wZTc5OGFlYTUzZjc0NTBkYmFkNjljOGI3NDUzZTUwMyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfZmJhNTlhNjUxMjBiNDdkMjlhNjk2YjczZWNlZDY4M2EgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjA2NjMzOTI1NDk0NCwgMi4zNjczMTc2NzY1NDQxODk1XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzBlNzk4YWVhNTNmNzQ1MGRiYWQ2OWM4Yjc0NTNlNTAzKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80ODcxMmI2Mzc0ZWU0ZDg3YmI2NGVjNDcwNmU1ODAwOCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2NjYyIsICJmaWxsT3BhY2l0eSI6IDEsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEsICJyYWRpdXMiOiAxMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMGU3OThhZWE1M2Y3NDUwZGJhZDY5YzhiNzQ1M2U1MDMpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2Y5MjY3MDY3MmFhODQ1Njc5OTI5NDEyM2NmNWZlOTU3ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wZTc5OGFlYTUzZjc0NTBkYmFkNjljOGI3NDUzZTUwMyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMjU3NzFkYjEzYjlkNDdhZmFjZjdiYzkzOWJhMzk4NGQgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzBlNzk4YWVhNTNmNzQ1MGRiYWQ2OWM4Yjc0NTNlNTAzKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9lNTg0N2U3Mjc2NDk0YjdkOGFkMTJiM2M1ZDUyNDljMyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wZTc5OGFlYTUzZjc0NTBkYmFkNjljOGI3NDUzZTUwMyk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMmRkYmQ5YmViZTNiNGVlY2IxNjc4YmNhNmJlNmQwMGIgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2NjYyIsICJmaWxsT3BhY2l0eSI6IDEsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEsICJyYWRpdXMiOiAxMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfMGU3OThhZWE1M2Y3NDUwZGJhZDY5YzhiNzQ1M2U1MDMpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzViNWVlYTAzNDBlYTQxYTY4YTFmZjI2ZTIxNGNlYzU2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODY1NzAyODUwODk1NzQ0LCAyLjM3MjM0OTUwMDY1NjEyOF0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF8wZTc5OGFlYTUzZjc0NTBkYmFkNjljOGI3NDUzZTUwMyk7CiAgICAgICAgCjwvc2NyaXB0Pg== onload=\"this.contentDocument.open();this.contentDocument.write(atob(this.getAttribute('data-html')));this.contentDocument.close();\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x7f58e0b79cd0>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = folium.Map(location=[48.868, 2.365], zoom_start=15)\n",
    "\n",
    "geojson = {\n",
    "    \"type\": \"FeatureCollection\",\n",
    "    \"features\": [\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [0, 1]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.357919216156006, 48.87621773324153],\n",
    "                    [2.357339859008789, 48.874834693731664],\n",
    "                    [2.362983226776123, 48.86855408432749],\n",
    "                    [2.362382411956787, 48.86796126699168],\n",
    "                    [2.3633265495300293, 48.86735432768131],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [2, 3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.351503372192383, 48.86443950493823],\n",
    "                    [2.361609935760498, 48.866775611250205],\n",
    "                    [2.3633265495300293, 48.86735432768131],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [1, 2]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.369627058506012, 48.86619159489603],\n",
    "                    [2.3724031448364253, 48.8626397112042],\n",
    "                    [2.3728322982788086, 48.8616233285001],\n",
    "                    [2.372767925262451, 48.86080456075567],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [0]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.3647427558898926, 48.86653565369396],\n",
    "                    [2.3647642135620117, 48.86630981023694],\n",
    "                    [2.3666739463806152, 48.86314789481612],\n",
    "                    [2.3673176765441895, 48.86066339254944],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [0, 1, 2, 3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.3633265495300293, 48.86735432768131],\n",
    "                    [2.3647427558898926, 48.86653565369396],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [1, 2, 3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.3647427558898926, 48.86653565369396],\n",
    "                    [2.3650002479553223, 48.86660622956524],\n",
    "                    [2.365509867668152, 48.866987337550164],\n",
    "                    [2.369627058506012, 48.86619159489603],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.369627058506012, 48.86619159489603],\n",
    "                    [2.372349500656128, 48.865702850895744],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "    ],\n",
    "}\n",
    "\n",
    "# manage overlays in groups to ease superposition order\n",
    "outlines = folium.FeatureGroup(\"outlines\")\n",
    "line_bg = folium.FeatureGroup(\"lineBg\")\n",
    "bus_lines = folium.FeatureGroup(\"busLines\")\n",
    "bus_stops = folium.FeatureGroup(\"busStops\")\n",
    "\n",
    "line_weight = 6\n",
    "line_colors = [\"red\", \"#08f\", \"#0c0\", \"#f80\"]\n",
    "stops = []\n",
    "for line_segment in geojson[\"features\"]:\n",
    "    # Get every bus line coordinates\n",
    "    segment_coords = [[x[1], x[0]] for x in line_segment[\"geometry\"][\"coordinates\"]]\n",
    "    # Get bus stops coordinates\n",
    "    stops.append(segment_coords[0])\n",
    "    stops.append(segment_coords[-1])\n",
    "    # Get number of bus lines sharing the same coordinates\n",
    "    lines_on_segment = line_segment[\"properties\"][\"lines\"]\n",
    "    # Width of segment proportional to the number of bus lines\n",
    "    segment_width = len(lines_on_segment) * (line_weight + 1)\n",
    "    # For the white and black outline effect\n",
    "    folium.PolyLine(\n",
    "        segment_coords, color=\"#000\", weight=segment_width + 5, opacity=1\n",
    "    ).add_to(outlines)\n",
    "    folium.PolyLine(\n",
    "        segment_coords, color=\"#fff\", weight=segment_width + 3, opacity=1\n",
    "    ).add_to(line_bg)\n",
    "    # Draw parallel bus lines with different color and offset\n",
    "    for j, line_number in enumerate(lines_on_segment):\n",
    "        plugins.PolyLineOffset(\n",
    "            segment_coords,\n",
    "            color=line_colors[line_number],\n",
    "            weight=line_weight,\n",
    "            opacity=1,\n",
    "            offset=j * (line_weight + 1) - (segment_width / 2) + ((line_weight + 1) / 2),\n",
    "        ).add_to(bus_lines)\n",
    "\n",
    "# Draw bus stops\n",
    "for stop in stops:\n",
    "    folium.CircleMarker(\n",
    "        stop,\n",
    "        color=\"#000\",\n",
    "        fill_color=\"#ccc\",\n",
    "        fill_opacity=1,\n",
    "        radius=10,\n",
    "        weight=4,\n",
    "        opacity=1,\n",
    "    ).add_to(bus_stops)\n",
    "\n",
    "outlines.add_to(m)\n",
    "line_bg.add_to(m)\n",
    "bus_lines.add_to(m)\n",
    "bus_stops.add_to(m)\n",
    "\n",
    "m"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
